package com.lagou.edu.config;

import com.lagou.edu.anno.Autowired;
import com.lagou.edu.anno.Service;
import com.lagou.edu.anno.Transaction;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.utils.ConnectionUtils;
import org.reflections.Reflections;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 该类负责扫描注解并解析
 */
public class AnnotionConfigParseBuilder {

    /**
     * 定义静态变量用于存放解析出来的对象值
     */
    private static final Map<String, Object> beanMap = new HashMap<>();
    /**
     * 定义静态变量用于存放解析出来的对象值，并且根据对象值来获取是否开启了声明式事务控制
     */
    private static final List<Object>  beanList = new ArrayList<>();


    /**
     * 初始化@Service注解
     * @param packageName
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     */
    public static void builderService(String packageName) throws Exception {
        // 通过packageName获取当前
        Reflections reflections = new Reflections(packageName);
        // 通过reflections.getTypesAnnotatedWith方法获取指定的注解的对象
        Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(Service.class);
        // 遍历获取得到的集合Set<Class<?>>
        for (Class<?> aClass : typesAnnotatedWith) {
            putObj(aClass, reflections);
        }
        System.out.println("创建对象完毕...........");
        System.out.println("依赖注入完毕...........");
        // 扫描是否开启了事务控制，如果开启事务控制将重写beanMap
        beanMap.entrySet().stream().forEach(bean -> {
            Class<?> aClass = bean.getValue().getClass();
            Transaction annotation = aClass.getAnnotation(Transaction.class);
            if(annotation != null){
                // 开启事务控制
                ProxyFactory proxyFactory = (ProxyFactory) AnnotionConfigParseBuilder.getBean("proxyFactory");
                //
                // 判断当前是否实现了接口
                Class<?>[] interfaces = aClass.getInterfaces();
                Object proxyObj;
                if(interfaces.length >= 1){
                    // 有接口实现，所以采用jdk动态代理
                    proxyObj = proxyFactory.getJdkProxy(bean.getValue());

                }else {
                    // 没有接口实现，所以采用cglib动态代理
                    proxyObj = proxyFactory.getCglibProxy(bean.getValue());
                }
                System.out.println("事务控制植入完毕...........");
                beanMap.put(bean.getKey(), proxyObj);
            }
        });


    }

    /**
     * 通过获取的对象进行赋值
     * @param aClass
     * @param reflections
     * @throws Exception
     */
    private static void putObj(Class<?> aClass, Reflections reflections) throws Exception{

        // 实例化对象
        Object bean = aClass.newInstance();
        // 获取注解的value属性值
        Service service = aClass.getAnnotation(Service.class);
        String value = service.value();

        // 定义bendId
        String beanId = value;
        // 判断当前value值是否有默认,如果没有则进行对应封装
        if(beanId == null || beanId.equals("")){
            // 给当前的注解设置一个默认的value属性值为当前类名称首字母小写
            String name = aClass.getName();
            String substring = name.substring(name.lastIndexOf(".") + 1, name.length());
            beanId = new StringBuilder().append(Character.toLowerCase(substring.charAt(0))).append(substring.substring(1)).toString();

        }
        // 获取所有变量,用于判断当前类是否有Autowired注解进行修饰
        Field[] declaredFields = aClass.getDeclaredFields();
        putFiled(declaredFields, reflections, bean);


        // 存入Map中
        beanMap.put(beanId, bean);

    }

    /**
     * 递归设置参数值
     * @param declaredFields
     * @param reflections
     * @param bean
     * @throws Exception
     */
    public static void putFiled(Field[] declaredFields, Reflections reflections, Object bean) throws Exception{
        for (Field declaredField : declaredFields) {
            // 设置暴力访问
            declaredField.setAccessible(true);
            if(declaredField.isAnnotationPresent(Autowired.class)){
                // 获取被Autowired修饰的对象
                Class<?> type = declaredField.getType();

                // 判断当前对象是类还是接口
                boolean anInterface = type.isInterface();
                // 实例化当前对象
                if(anInterface){
                    // 获取该接口的实现类
                    Set<Class<?>> subTypesOf = reflections.getSubTypesOf((Class<Object>) type);
                    // 遍历当前接口实现类,如果当前接口只有一个实现类，那么将默认将该对象获取到
                    if(subTypesOf.size() == 1){
                        // 获取实现类
                        Class<?> subClass = subTypesOf.iterator().next();
                        Object subObj = subClass.newInstance();
                        // 获取当前实现类中的字段
                        Field[] subClassDeclaredFields = subClass.getDeclaredFields();
                        declaredField.set(bean, subObj);
                        putFiled(subClassDeclaredFields, reflections, subObj);
                    }else if(subTypesOf.size() > 1){
                        // 当前接口实现类不知一个，通过beanID获取对应的对象，并注入到当前的对象中
                        System.out.println("暂不支持此功能，敬请期待.........");
                    }
                }else {
                    Field[] typeDeclaredFields = type.getDeclaredFields();
                    Object newInstance = type.newInstance();
                    if(type.getName().equals("com.lagou.edu.utils.ConnectionUtils")){
                        // 先从工厂获取是否存在connectionUtils,如果不存在那么新建
                        Object connectionUtils = beanMap.get("connectionUtils");
                        if(connectionUtils == null){
                            beanMap.put("connectionUtils", new ConnectionUtils());
                        }
                        newInstance =  beanMap.get("connectionUtils");
                    }
                    declaredField.set(bean, newInstance);
                    putFiled(typeDeclaredFields, reflections, newInstance);
                }
            }
        }
    }




    /**
     * 通过beanId获取bean
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return beanMap.get(name);
    }
}
